<template>
  <div class="image-hotspot-editor">
    <div class="editor-header">
      <h3>图片热区编辑器</h3>
      <el-button type="primary" size="small" @click="addHotspot">添加热区</el-button>
    </div>

    <div class="editor-container" ref="editorContainer">
      <div
        class="image-container"
        ref="imageContainer"
        @mousedown="onImageMouseDown"
      >
        <img :src="imageUrl" @load="onImageLoad" ref="image" />

        <!-- 绘制中的热区 -->
        <div
          v-if="isDrawing"
          class="hotspot drawing"
          :style="{
            left: `${drawStartX}px`,
            top: `${drawStartY}px`,
            width: `${drawWidth}px`,
            height: `${drawHeight}px`
          }"
        ></div>

        <!-- 热区列表 -->
        <div
          v-for="(hotspot, index) in hotspots"
          :key="index"
          class="hotspot"
          :class="{ 'active': selectedHotspotIndex === index }"
          :style="{
            left: `${hotspot.x}px`,
            top: `${hotspot.y}px`,
            width: `${hotspot.width}px`,
            height: `${hotspot.height}px`
          }"
          @mousedown.stop="onHotspotMouseDown($event, index)"
          @click.stop="selectHotspot(index)"
        >
          <div class="hotspot-info">区域 {{ index + 1 }}</div>

          <!-- 拖动控制点 -->
          <div
            v-for="(handle, hIndex) in resizeHandles"
            :key="hIndex"
            class="resize-handle"
            :class="handle.class"
            @mousedown.stop="onResizeHandleMouseDown($event, index, handle.position)"
          ></div>
        </div>
      </div>
    </div>

    <div class="hotspot-list">
      <h4>热区列表</h4>
      <ul>
        <li
          v-for="(hotspot, index) in hotspots"
          :key="index"
          :class="{ 'active': selectedHotspotIndex === index }"
          @click="selectHotspot(index)"
        >
          热区 {{ index + 1 }} - {{ hotspot.width }}x{{ hotspot.height }}
          <el-button type="danger" size="mini" @click.stop="removeHotspot(index)">删除</el-button>
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  name: 'ImageHotspotEditor',
  props: {
    imageUrl: {
      type: String,
      required: true
    },
    value: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      hotspots: [],
      selectedHotspotIndex: -1,
      isDragging: false,
      isResizing: false,
      isDrawing: false,
      dragStartX: 0,
      dragStartY: 0,
      resizeStartWidth: 0,
      resizeStartHeight: 0,
      resizeStartX: 0,
      resizeStartY: 0,
      currentResizeHandle: '',
      imageWidth: 0,
      imageHeight: 0,
      // 新增绘制热区相关的属性
      drawStartX: 0,
      drawStartY: 0,
      drawWidth: 0,
      drawHeight: 0,
      resizeHandles: [
        { position: 'tl', class: 'top-left' },
        { position: 'tm', class: 'top-middle' },
        { position: 'tr', class: 'top-right' },
        { position: 'ml', class: 'middle-left' },
        { position: 'mr', class: 'middle-right' },
        { position: 'bl', class: 'bottom-left' },
        { position: 'bm', class: 'bottom-middle' },
        { position: 'br', class: 'bottom-right' }
      ]
    };
  },
  watch: {
    value: {
      handler(newVal) {
        this.hotspots = JSON.parse(JSON.stringify(newVal));
      },
      immediate: true
    },
    hotspots: {
      handler(newVal) {
        this.$emit('input', JSON.parse(JSON.stringify(newVal)));
      },
      deep: true
    }
  },
  mounted() {
    window.addEventListener('mousemove', this.onMouseMove);
    window.addEventListener('mouseup', this.onMouseUp);
    window.addEventListener('keydown', this.onKeyDown);
  },
  beforeUnmount() {  // Vue 3 使用 beforeUnmount 替代 beforeDestroy
    window.removeEventListener('mousemove', this.onMouseMove);
    window.removeEventListener('mouseup', this.onMouseUp);
    window.removeEventListener('keydown', this.onKeyDown);
  },
  methods: {
    onImageLoad() {
      if (this.$refs.image) {
        this.imageWidth = this.$refs.image.naturalWidth;
        this.imageHeight = this.$refs.image.naturalHeight;
      }
    },
    addHotspot() {
      // 添加一个新的热区，默认大小100x100，位置在图片中央
      const containerRect = this.$refs.imageContainer.getBoundingClientRect();
      const defaultWidth = 100;
      const defaultHeight = 100;

      const newHotspot = {
        x: (containerRect.width / 2) - (defaultWidth / 2),
        y: (containerRect.height / 2) - (defaultHeight / 2),
        width: defaultWidth,
        height: defaultHeight,
        link: ''
      };

      this.hotspots.push(newHotspot);
      this.selectedHotspotIndex = this.hotspots.length - 1;
    },
    selectHotspot(index) {
      this.selectedHotspotIndex = index;
    },
    removeHotspot(index) {
      this.hotspots.splice(index, 1);
      if (this.selectedHotspotIndex === index) {
        this.selectedHotspotIndex = -1;
      } else if (this.selectedHotspotIndex > index) {
        this.selectedHotspotIndex--;
      }
    },
    onHotspotMouseDown(event, index) {
      this.selectedHotspotIndex = index;
      this.isDragging = true;

      const hotspot = this.hotspots[index];
      this.dragStartX = event.clientX;
      this.dragStartY = event.clientY;
      this.resizeStartX = hotspot.x;
      this.resizeStartY = hotspot.y;

      event.preventDefault();
    },
    onResizeHandleMouseDown(event, index, handlePosition) {
      this.selectedHotspotIndex = index;
      this.isResizing = true;
      this.currentResizeHandle = handlePosition;

      const hotspot = this.hotspots[index];
      this.dragStartX = event.clientX;
      this.dragStartY = event.clientY;
      this.resizeStartWidth = hotspot.width;
      this.resizeStartHeight = hotspot.height;
      this.resizeStartX = hotspot.x;
      this.resizeStartY = hotspot.y;

      event.preventDefault();
    },
    // 新增在图片上按下鼠标的处理函数
    onImageMouseDown(event) {
      // 只有当点击在图片上，而非热区上时才启动绘制模式
      if (event.target === this.$refs.image) {
        const containerRect = this.$refs.imageContainer.getBoundingClientRect();
        const offsetX = event.clientX - containerRect.left;
        const offsetY = event.clientY - containerRect.top;

        // 开始绘制热区
        this.isDrawing = true;
        this.drawStartX = offsetX;
        this.drawStartY = offsetY;
        this.drawWidth = 0;
        this.drawHeight = 0;

        // 取消选中的热区
        this.selectedHotspotIndex = -1;

        event.preventDefault();
      }
    },
    onMouseMove(event) {
      if (this.isDrawing) {
        // 计算当前鼠标位置相对于图片容器的偏移
        const containerRect = this.$refs.imageContainer.getBoundingClientRect();
        const currentX = event.clientX - containerRect.left;
        const currentY = event.clientY - containerRect.top;

        // 计算绘制热区的宽高
        this.drawWidth = currentX - this.drawStartX;
        this.drawHeight = currentY - this.drawStartY;

        // 处理反向拖动（如果用户从右到左或从下到上拖动）
        if (this.drawWidth < 0) {
          this.drawWidth = Math.abs(this.drawWidth);
          this.drawStartX = currentX;
        }

        if (this.drawHeight < 0) {
          this.drawHeight = Math.abs(this.drawHeight);
          this.drawStartY = currentY;
        }

        return;
      }

      if (!this.isDragging && !this.isResizing) return;

      const deltaX = event.clientX - this.dragStartX;
      const deltaY = event.clientY - this.dragStartY;

      if (this.isResizing && this.selectedHotspotIndex !== -1) {
        // 创建修改后的热区对象
        const newHotspot = { ...this.hotspots[this.selectedHotspotIndex] };

        switch(this.currentResizeHandle) {
          case 'tl': // 左上
            newHotspot.x = this.resizeStartX + deltaX;
            newHotspot.y = this.resizeStartY + deltaY;
            newHotspot.width = this.resizeStartWidth - deltaX;
            newHotspot.height = this.resizeStartHeight - deltaY;
            break;
          case 'tm': // 上中
            newHotspot.y = this.resizeStartY + deltaY;
            newHotspot.height = this.resizeStartHeight - deltaY;
            break;
          case 'tr': // 右上
            newHotspot.y = this.resizeStartY + deltaY;
            newHotspot.width = this.resizeStartWidth + deltaX;
            newHotspot.height = this.resizeStartHeight - deltaY;
            break;
          case 'ml': // 左中
            newHotspot.x = this.resizeStartX + deltaX;
            newHotspot.width = this.resizeStartWidth - deltaX;
            break;
          case 'mr': // 右中
            newHotspot.width = this.resizeStartWidth + deltaX;
            break;
          case 'bl': // 左下
            newHotspot.x = this.resizeStartX + deltaX;
            newHotspot.width = this.resizeStartWidth - deltaX;
            newHotspot.height = this.resizeStartHeight + deltaY;
            break;
          case 'bm': // 下中
            newHotspot.height = this.resizeStartHeight + deltaY;
            break;
          case 'br': // 右下
            newHotspot.width = this.resizeStartWidth + deltaX;
            newHotspot.height = this.resizeStartHeight + deltaY;
            break;
        }

        // 确保热区尺寸不小于最小尺寸
        if (newHotspot.width < 20) newHotspot.width = 20;
        if (newHotspot.height < 20) newHotspot.height = 20;

        // 更新热区 - Vue 3 方式
        this.hotspots[this.selectedHotspotIndex] = newHotspot;
      }

      if (this.isDragging && this.selectedHotspotIndex !== -1) {
        const containerRect = this.$refs.imageContainer.getBoundingClientRect();
        // 创建修改后的热区对象
        const newHotspot = { ...this.hotspots[this.selectedHotspotIndex] };

        // 计算新位置
        newHotspot.x = this.resizeStartX + deltaX;
        newHotspot.y = this.resizeStartY + deltaY;

        // 边界检查：确保热区不能拖出图片区域
        if (newHotspot.x < 0) newHotspot.x = 0;
        if (newHotspot.y < 0) newHotspot.y = 0;
        if (newHotspot.x + newHotspot.width > containerRect.width) {
          newHotspot.x = containerRect.width - newHotspot.width;
        }
        if (newHotspot.y + newHotspot.height > containerRect.height) {
          newHotspot.y = containerRect.height - newHotspot.height;
        }

        // 更新热区 - Vue 3 方式
        this.hotspots[this.selectedHotspotIndex] = newHotspot;
      }
    },
    onMouseUp() {
      // 如果是在绘制模式，则完成热区绘制
      if (this.isDrawing) {
        // 如果绘制的热区大小超过最小阈值，则添加为新热区
        if (this.drawWidth > 20 && this.drawHeight > 20) {
          const newHotspot = {
            x: this.drawStartX,
            y: this.drawStartY,
            width: this.drawWidth,
            height: this.drawHeight,
            link: ''
          };

          this.hotspots.push(newHotspot);
          this.selectedHotspotIndex = this.hotspots.length - 1;
        }

        // 重置绘制状态
        this.isDrawing = false;
      }

      this.isDragging = false;
      this.isResizing = false;
    },
    onKeyDown(event) {
      // 按下Delete键删除当前选中的热区
      if (event.key === 'Delete' && this.selectedHotspotIndex !== -1) {
        this.removeHotspot(this.selectedHotspotIndex);
      }
    }
  }
};
</script>

<style scoped>
	.image-hotspot-editor {
		display: flex;
		flex-direction: column;
		width: 100%;
		height: 100%;
		border: 1px solid #ebeef5;
		border-radius: 4px;
		overflow: hidden;
	}

	.editor-header {
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 12px 16px;
		border-bottom: 1px solid #ebeef5;
	}

	.editor-container {
		position: relative;
		flex: 1;
		overflow: auto;
		padding: 20px;
		background-color: #f5f7fa;
		display: flex;
		justify-content: center;
	}

	.image-container {
		position: relative;
		display: inline-block;
		user-select: none;
	}

	.image-container img {
		display: block;
		max-width: 100%;
	}

	.hotspot {
		position: absolute;
		background-color: rgba(24, 144, 255, 0.2);
		border: 1px solid rgba(24, 144, 255, 0.5);
		cursor: move;
		box-sizing: border-box;
	}

	.hotspot.active {
		border: 2px solid #409eff;
		background-color: rgba(24, 144, 255, 0.3);
		z-index: 10;
	}

	.hotspot-info {
		position: absolute;
		top: -22px;
		left: 0;
		font-size: 12px;
		color: #fff;
		background-color: #409eff;
		padding: 2px 6px;
		border-radius: 2px;
	}

	.resize-handle {
		position: absolute;
		width: 8px;
		height: 8px;
		background-color: #fff;
		border: 1px solid #409eff;
		border-radius: 4px;
	}

	.top-left {
		top: -4px;
		left: -4px;
		cursor: nwse-resize;
	}

	.top-middle {
		top: -4px;
		left: 50%;
		transform: translateX(-50%);
		cursor: ns-resize;
	}

	.top-right {
		top: -4px;
		right: -4px;
		cursor: nesw-resize;
	}

	.middle-left {
		top: 50%;
		left: -4px;
		transform: translateY(-50%);
		cursor: ew-resize;
	}

	.middle-right {
		top: 50%;
		right: -4px;
		transform: translateY(-50%);
		cursor: ew-resize;
	}

	.bottom-left {
		bottom: -4px;
		left: -4px;
		cursor: nesw-resize;
	}

	.bottom-middle {
		bottom: -4px;
		left: 50%;
		transform: translateX(-50%);
		cursor: ns-resize;
	}

	.bottom-right {
		bottom: -4px;
		right: -4px;
		cursor: nwse-resize;
	}

	.hotspot-list {
		padding: 12px 16px;
		border-top: 1px solid #ebeef5;
		max-height: 200px;
		overflow-y: auto;
	}

	.hotspot-list h4 {
		margin-top: 0;
		margin-bottom: 12px;
	}

	.hotspot-list ul {
		list-style: none;
		padding: 0;
		margin: 0;
	}

	.hotspot-list li {
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 8px 12px;
		background-color: #f5f7fa;
		margin-bottom: 8px;
		border-radius: 4px;
		cursor: pointer;
	}

	.hotspot-list li.active {
		background-color: #ecf5ff;
		color: #409eff;
	}
</style>
